#pragma once

#include <iostream>
#include <queue>
#include <pthread.h> //原生线程库
#include <mutex>     //锁
#include <unistd.h>
#include "lockGuard.hpp"
using namespace std;

const int gDefaultCap = 5;

template <class T>
class BlockQueue
{
private:
    bool isQueueEmpty()
    {
        return bq_.size() == 0;
    }
    bool isQueueFull()
    {
        return bq_.size() == capecity_;
    }

public:
    BlockQueue(int capecity = gDefaultCap)
        : capecity_(capecity)
    {
        pthread_mutex_init(&mtx_, nullptr);  // 初始化互斥锁
        pthread_cond_init(&Empty_, nullptr); // 初始化条件变量
        pthread_cond_init(&Full_, nullptr);
    }

    void Push(const T &in)
    {

        lockGuard lockguard(&mtx_); // 构造锁守卫，并自动加锁
        while (isQueueFull())
        {
            pthread_cond_wait(&Full_, &mtx_);
        }
        bq_.push(in);
        pthread_cond_signal(&Empty_);
        // 出作用域守卫析构自动解锁

        // pthread_mutex_lock(&mtx_);
        // 检测是否空间满
        // while(isQueueFull())
        //{
        // 如果队列满了就没有办法写入，所以必须让生产者的写入工作等待
        // pthread_cond_wait(&Full_,&mtx_);
        //}
        // 访问资源（唤醒后/没满）
        // bq_.push(in);
        // pthread_cond_signal(&Empty_);
        // 唤醒策略：当资源生产到总数的一半时，再唤醒消费者
        // if(bq_.size() >= (capecity_/2))
        // {
        //     pthread_cond_signal(&Empty_);
        // }
        // pthread_mutex_unlock(&mtx_);
        // pthread_cond_signal(&Empty_);
        // 生产者生产后，资源被补充，唤醒消费者消费
    }

    void Pop(T *out)
    {

        lockGuard lockguard(&mtx_);
        while (isQueueEmpty())
        {
            pthread_cond_wait(&Empty_, &mtx_);
        }
        *out = bq_.front();
        bq_.pop();
        pthread_cond_signal(&Full_);

        // pthread_mutex_lock(&mtx_);
        // while(isQueueEmpty())
        // {
        //     //若资源为空，则进行等待
        //     pthread_cond_wait(&Empty_,&mtx_);
        // }
        // *out = bq_.front();
        // bq_.pop();
        // pthread_mutex_unlock(&mtx_);
        // pthread_cond_signal(&Full_);
        // 消费者消费后，资源恢复，唤醒生产者
    }

    ~BlockQueue()
    {
        // 释放锁和条件变量
        pthread_mutex_destroy(&mtx_);
        pthread_cond_destroy(&Empty_);
        pthread_cond_destroy(&Full_);
    }

private:
    queue<T> bq_;
    int capecity_;         // 容量
    pthread_mutex_t mtx_;  // 互斥锁 保证阻塞队列安全
    pthread_cond_t Empty_; // 条件变量 用于表示bq是否资源为 空
    pthread_cond_t Full_;  // 条件变量 用于表示bq是否 满
};